using System;
using Qyoto;
using System.Collections.Generic;

namespace Shlick
{
	using Object = Clandestine.Engines.Field.Object;
	
	public class ObjectMenu : QObject, IContextMenu
	{
		public MapDocument MapDocument { get; private set; }
		private List<Object> selectedObjects;
		private QMenu menu;
		private QSignalMapper signalMapper;
		
		public ObjectMenu(MapDocument mapDocument, List<Object> objs)
		{
			this.MapDocument = mapDocument;
			this.selectedObjects = objs;

			/*
			 * Easiest to make QActions for each menu item here and then add the appropriate ones depending
			 * on the number of objects selected later. The extra work to create unused ones is not noticable!
			 */
			 
			menu = new QMenu(this.MapDocument.GLWidget);
			
			QAction actionMove = new QAction(new QIcon(":/tango/png/art-libre/transform-move.png"), "Move Object", menu);
			Connect(actionMove, SIGNAL("triggered()"), this, SLOT("onMoveSelect()"));
			
			QAction actionDelete = new QAction(new QIcon(":/tango/scalable/actions/edit-delete.svg"), "Delete Object", menu);
			Connect(actionDelete, SIGNAL("triggered()"), this, SLOT("onDeleteSelect()"));
			
			QAction actionEdit = new QAction(new QIcon(":/tango/scalable/categories/applications-graphics.svg"), "Edit Object", menu);
			Connect(actionEdit, SIGNAL("triggered()"), this, SLOT("onEditSelect()"));
			
			QAction actionSave = new QAction(new QIcon(":/tango/scalable/actions/document-save.svg"), "Save to File", menu);
			Connect(actionSave, SIGNAL("triggered()"), this, SLOT("onSaveSelect()"));
			
			// Make a submenu with all the individual objects they can select
			QMenu selectObjectsMenu = new QMenu("Select Single Object", menu);
			signalMapper = new QSignalMapper(selectObjectsMenu); // signal mapper allows us to pass an int to identify the object selected to the SLOT
			Connect(signalMapper, SIGNAL("mapped(int)"), this, SLOT("onSelectObject(int)"));
			for (int i = 0; i < selectedObjects.Count; i++)
			{	
				QAction action = new QAction("Name: " + selectedObjects[i].Name, menu);
				Connect(action, SIGNAL("triggered()"), signalMapper, SLOT("map()"));
				signalMapper.SetMapping(action, i);
				selectObjectsMenu.AddAction(action);
			} 
			
			/*
			 *  Now construct the menu depending on how many objects we have!
			 */
			if (selectedObjects.Count == 1)
			{
				menu.AddAction(actionMove);
				menu.AddAction(actionEdit);
				menu.AddAction(actionDelete);
				menu.AddSeparator();
				menu.AddAction(actionSave);
			} 
			else if (selectedObjects.Count > 1)
			{
				menu.AddAction(actionMove);
				menu.AddAction(actionDelete);
				menu.AddSeparator();
				menu.AddMenu(selectObjectsMenu);
			}
			else
				throw new NotImplementedException("Todo: right click 0 objects presents add new object?");
		}	
		
		public void Show()
		{
			menu.Exec(QCursor.Pos());
		}
		
		// int selected == index of the selected object in selectedObjects
		[Q_SLOT("onSelectObject(int)")]
		private void onSelectObject(int selected)
		{
			Object o = selectedObjects[selected];
			
			// Deslect all object
			foreach (Object obj in selectedObjects)
				obj.Deselect();
			selectedObjects.Clear();
			
			// Just select the given one
			o.Select();
			selectedObjects.Add(o);
		}
		
		[Q_SLOT("onSaveSelect()")]
		private void onSaveSelect()
		{
			string filename = "zzz-end-of-list.xml";
			
			// only ever 1 item in selectedObjects when this is called.
			this.selectedObjects[0].SaveToFile(filename);
		}
		
		[Q_SLOT("onMoveSelect()")]
		private void onMoveSelect()
		{
			// Open MoveObjectTool
			this.MapDocument.ToolManager.OpenNewTool(ToolTypes.ObjectMove, this.selectedObjects); 
		}

		[Q_SLOT("onDeleteSelect()")]
		private void onDeleteSelect()
		{
			// Delete! Simples.
			this.MapDocument.CommandManager.Do(ObjectDeleteCommand.DeleteMultiple(this.selectedObjects)); 
		}
		
		[Q_SLOT("onEditSelect()")]
		private void onEditSelect()
		{
			// Edit!
			this.MapDocument.EditObject(this.selectedObjects[0]); // will only ever get called when one object is selected, if not, oh well.
		}
	}
}

